package com.master.access;

import com.alibaba.fastjson.JSONObject;
import com.master.config.HostHolder;
import com.master.redis.AccessKey;
import com.master.redis.RedisServer;
import com.master.util.CodeMsg;
import com.master.util.Result;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;

@Service
public class AccessInterceptor implements HandlerInterceptor {

    @Autowired
    HostHolder hostHolder;

    @Autowired
    RedisServer redisServer;

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        if(handler instanceof HandlerMethod){
            if(hostHolder.getUser() == null){
                render(httpServletResponse,CodeMsg.SESSION_ERROR);
                return false;
            }
            HandlerMethod hm = (HandlerMethod)handler;
            AccessLimit accessLimit = hm.getMethodAnnotation(AccessLimit.class);
            if(accessLimit == null){
                //AccessLimit为null表示不做任何限流
                return true;
            }
            String key = httpServletRequest.getRequestURI();
            key += "_" + hostHolder.getUser().getId();
            int seconds = accessLimit.seconds();
            int maxCount = accessLimit.maxCount();

            Integer count = redisServer.get(AccessKey.withExpire(seconds),key,Integer.class);
            if(count == null){
                //表明还没有访问过
                redisServer.set(AccessKey.withExpire(seconds),key,1);
            }else if(count < 5){
                //如果访问次数小于5次,直接增加一次访问次数
                redisServer.incr(AccessKey.withExpire(seconds),key);
            }else{
                //访问过于频繁
                //将结果要返回给浏览器
                render(httpServletResponse,CodeMsg.ACCESS_LIMIT_REACHE);
                return false;
            }

        }
        return true;
    }

    //向浏览器发送JSON格式数据
    private void render(HttpServletResponse response,CodeMsg accessLimit) throws IOException {
        response.setContentType("application/json;charset=UTF-8");
        OutputStream out = response.getOutputStream();
        String str = JSONObject.toJSONString(Result.error(accessLimit));
        out.write(str.getBytes("UTF-8"));
        out.flush();
        out.close();
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
